home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_085 / vnews / vnews.c < prev   
C/C++ Source or Header  |  1992-05-06  |  12KB  |  472 lines

  1. /************************************************************
  2.   Vnews
  3.  
  4.   Copyright By: Stephen Vermeulen 1987.
  5.                 3635 Utah Dr. N.W.,
  6.                 Calgary, Alberta,
  7.                 CANADA, T2N 4A6
  8.  
  9.   This program is designed to be a simple news file reader.
  10.   The user invokes it with the name of the directory containing
  11.   the news files he wants to read.  The program then allows
  12.   him to read these files easily.
  13.  
  14.   Syntax:
  15.  
  16.          vnews [dir_name [first_file]]
  17.  
  18.          vnews dir_name
  19.  
  20.            will display the contents of all the files in
  21.            the directory named dir_name.
  22.  
  23.          vnews
  24.  
  25.            will display the contents of all the files in
  26.            the current directory.
  27.  
  28.          vnews dir_name first_file
  29.  
  30.            will allow you to read all the files within the
  31.            directory "dir_name" and will start you at
  32.            file "first_file"
  33.  
  34. NOTE:  some aspects of the code are clearly examples of how
  35.        not to code in C!  Ie: I have made extensive and
  36.        unforgivable use of the GOTO statement...
  37.  
  38. NOTE2: This compiles under Lattice 3.1 only, sorry...
  39.  
  40. ************************************************************/
  41.  
  42. #include <intuition/intuition.h>
  43. #include <graphics/gfxmacros.h>
  44. #include <stdio.h>
  45. #include <string.h>
  46.  
  47. #define PGUP 1
  48. #define PGDN 2
  49. #define NEXT 3
  50. #define PREV 4
  51.  
  52. struct IntuitionBase *IntuitionBase;  /* to use intuition functions */
  53. struct GfxBase *GfxBase;              /* to use graphics functions  */
  54.  
  55. /************************************************************
  56.   The following stuff sets up the window to be used to display
  57.   the text along with its gadgets that advance you through
  58.   the text of a single message, of from message to message.
  59.  
  60.   The following gadgets are provided:
  61.  
  62.     PgUp  - display next page of the current message
  63.     PgDn  - displays the previous page of the current message
  64.     Next  - displays the next message
  65.     Prev  - displays the previous message
  66.  
  67.   These all live in the title bar, along with the name of
  68.   the file that is being displayed.
  69. ************************************************************/
  70.  
  71. #define LEFT_OFFSET 410
  72.  
  73. struct IntuiText pgup_text =
  74. {
  75.   1, 0, JAM2, 0, 0, NULL, (UBYTE *) "Prev", NULL
  76. };
  77.  
  78. struct IntuiText pgdn_text =
  79. {
  80.   1, 0, JAM2, 0, 0, NULL, (UBYTE *) "back", NULL
  81. };
  82.  
  83. struct IntuiText next_text =
  84. {
  85.   1, 0, JAM2, 0, 0, NULL, (UBYTE *) "fore", NULL
  86. };
  87.  
  88. struct IntuiText prev_text =
  89. {
  90.   1, 0, JAM2, 0, 0, NULL, (UBYTE *) "Next", NULL
  91. };
  92.  
  93. struct Gadget pgup_gad =
  94. {
  95.   NULL,
  96.   LEFT_OFFSET, 0, 32, 10,
  97.   GADGHCOMP, RELVERIFY | TOPBORDER,  BOOLGADGET,
  98.   NULL, NULL,
  99.   &pgup_text,
  100.   NULL,  NULL,  PREV,  NULL
  101. };
  102.  
  103. struct Gadget pgdn_gad =
  104. {
  105.   &pgup_gad,
  106.   LEFT_OFFSET+48, 0, 32, 10,
  107.   GADGHCOMP, RELVERIFY | TOPBORDER,  BOOLGADGET,
  108.   NULL, NULL,
  109.   &pgdn_text,
  110.   NULL,  NULL,  PGDN,  NULL
  111. };
  112.  
  113. struct Gadget next_gad =
  114. {
  115.   &pgdn_gad,
  116.   LEFT_OFFSET+96, 0, 32, 10,
  117.   GADGHCOMP, RELVERIFY | TOPBORDER,  BOOLGADGET,
  118.   NULL, NULL,
  119.   &next_text,
  120.   NULL,  NULL,  PGUP,  NULL
  121. };
  122.  
  123. struct Gadget prev_gad =
  124. {
  125.   &next_gad,
  126.   LEFT_OFFSET+144, 0, 32, 10,
  127.   GADGHCOMP, RELVERIFY | TOPBORDER,  BOOLGADGET,
  128.   NULL, NULL,
  129.   &prev_text,
  130.   NULL,  NULL,  NEXT,  NULL
  131. };
  132.  
  133. struct NewWindow nw =
  134. {
  135.   0, 3, 640, 200 - 3,
  136.   -1, -1,
  137.   GADGETUP | CLOSEWINDOW,
  138.   WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH | BORDERLESS | ACTIVATE,
  139.   &prev_gad,
  140.   NULL,
  141.   NULL,
  142.   NULL, /* default screen */
  143.   NULL, /* no special bm */
  144.   0, 0, -1, -1,
  145.   WBENCHSCREEN
  146. };
  147.  
  148. /************************************************************
  149.   allow space for about 500 files in the directory.
  150. ************************************************************/
  151.  
  152. char names[40000], *pointers[500];
  153. char dir_name[100];
  154.  
  155. /************************************************************
  156.   This array is used to hold offsets from the start of the
  157.   file to the nth page in it, so the PgDn function works, as
  158.   the file is paged through by hitting PgUp the position of
  159.   each page start is entered into the array, then when PgDn
  160.   is hit you can easily backup.
  161. ************************************************************/
  162.  
  163. unsigned long int page_top[1000];
  164. short current_page;  /* index for the page_top array */
  165. short current_file;  /* index for the file name array */
  166. struct Window *w;
  167. FILE *in;
  168.  
  169. /************************************************************
  170.   The display_page() function displays a page of text from
  171.   the file on the screen.  It first clears the window, then
  172.   it does a line by line display of the file, it reads from
  173.   the line one line of text at a time, printing each line of
  174.   text to the window and then advancing to the next line on
  175.   the window, when it has printed 23 lines of text the process
  176.   stops.
  177. ************************************************************/
  178.  
  179. char temp_buf[200];
  180.  
  181. /************************************************************
  182.   The clean_string function removes CR's from the text string
  183.   and expands tabs out to 2 spaces each.
  184. ************************************************************/
  185.  
  186. void clean_string(s)
  187. register char *s;
  188. {
  189.   register int n;
  190.   register int i;
  191.  
  192.   n = strlen(s);
  193.   if (n)
  194.   {
  195.     if (strpbrk(s, "\11\15\12"))
  196.     {
  197.       for (i = 0; i < n; ++i)
  198.       {
  199.         switch(s[i])
  200.         {
  201.           case 10:  /* line feed -- replace with space */
  202.           case 13:  /* carriage return -- replace with space */
  203.             s[i] = ' ';
  204.             break;
  205.           case 9:   /* tab -- expand to 2 spaces */
  206.             s[i] = ' ';
  207.             memcpy(s + i + 2, s + i + 1, n - i);
  208.             s[i+1] = ' ';
  209.             ++n;
  210.             break;
  211.         }
  212.       }
  213.     }
  214.   }
  215. }
  216.  
  217. void display_page()
  218. {
  219.   int dy;
  220.  
  221.   SetAPen(w->RPort, 0);
  222.   RectFill(w->RPort, 0, w->BorderTop + 1,
  223.                      w->Width - 1, w->Height - w->BorderBottom);
  224.   SetAPen(w->RPort, 1);
  225.   dy = w->RPort->TxHeight;
  226.   Move(w->RPort, 0, w->BorderTop + dy);
  227.   while((w->RPort->cp_y + dy) < w->Height) /* enough room */
  228.   {
  229.     if (fgets(temp_buf, 80, in))
  230.     {
  231.       temp_buf[80] = 0;      /* always force an end of string here
  232.                                 as fgets does not put one in if 80
  233.                                 characters were read before any
  234.                                 end of line type character was hit
  235.                               */
  236.       clean_string(temp_buf);
  237.  
  238.       /*********************************************
  239.         This is not the best way of doing it, because
  240.         lines that are longer than about 80 characters
  241.         get truncated.  One should really break long
  242.         lines appropriately so that all the text does
  243.         get displayed.
  244.  
  245.         This problem has been partially eliminated
  246.         by reading in only 80 character chunks from
  247.         the file by the fgets() function.  This is
  248.         not the true solution because it depends on the
  249.         font that is being used.
  250.       *********************************************/
  251.  
  252.       Text(w->RPort, temp_buf, strlen(temp_buf));
  253.       w->RPort->cp_x = 0;
  254.       w->RPort->cp_y += dy;
  255.     }
  256.     else  /* we have reached EOF */
  257.     {
  258.       clean_string(temp_buf);
  259.       Text(w->RPort, temp_buf, strlen(temp_buf));
  260.       goto eof_stop;
  261.     }
  262.   }
  263. eof_stop:
  264. }
  265.  
  266. /************************************************************
  267.   The next_page() function has three modes depending on the
  268.   value of n:
  269.  
  270.     -1  - Move to the previous page and display one page of the
  271.           file.
  272.  
  273.      0  - Display the file from the very first line.
  274.  
  275.     +1  - Move the file to the next page and display it.
  276. ************************************************************/
  277.  
  278. void next_page(n)
  279. short n;
  280. {
  281.   unsigned long int pos;
  282.  
  283.   if (!in) return;
  284.   switch(n)
  285.   {
  286.     case -1:
  287.       if (current_page) --current_page;
  288.       fseek(in, page_top[current_page], 0);
  289.       display_page();
  290.       break;
  291.     case 0:
  292.       current_page = 0;
  293.       page_top[0] = 0;
  294.       display_page();
  295.       break;
  296.     case 1:
  297.       pos = ftell(in);
  298.       if (pos != EOF)
  299.       {
  300.         if (current_page < 1000) ++current_page;
  301.         page_top[current_page] = pos;
  302.         display_page();
  303.       }
  304.       break;
  305.   }
  306. }
  307.  
  308. /************************************************************
  309.   The next file function has three modes depending on the
  310.   value of n:
  311.  
  312.   -1 - Move to the previous file in the file list.
  313.    0 - Open the very first file in the file list.
  314.   +1 - Move to the next file in the file list.
  315. ************************************************************/
  316.  
  317. void next_file(n)
  318. short n;
  319. {
  320.   switch(n)
  321.   {
  322.     case -1:
  323.       if (current_file) --current_file;
  324.       if (in) fclose(in);
  325.       in = fopen(pointers[current_file], "r");
  326.       break;
  327.     case 0:
  328.       current_file = 0;
  329.       in = fopen(pointers[current_file], "r");
  330.       break;
  331.     case 1:
  332.       if (current_file < 500) ++current_file;
  333.       if (in) fclose(in);
  334.       in = fopen(pointers[current_file], "r");
  335.       break;
  336.   }
  337.   if (in)
  338.   {
  339.     SetWindowTitles(w, pointers[current_file], -1);
  340.   }
  341.   else
  342.   {
  343.     SetWindowTitles(w, "No more news!", -1);
  344.   }
  345. }
  346.  
  347. char start_name[90];
  348.  
  349. void main(argc, argv)
  350. int argc;
  351. char *argv[];
  352. {
  353.   int count, flag;
  354.   int func, class;
  355.   struct IntuiMessage *mess;
  356.  
  357.   printf("\nVnews  - a news file reader was brought to you by:\n");
  358.   printf("         Stephen Vermeulen,\n");
  359.   printf("         3635 Utah Dr. N.W.,\n");
  360.   printf("         Calgary, Alberta,\n");
  361.   printf("         CANADA, T2N 4A6\n");
  362.   printf("Copyright 1987 by Stephen Vermeulen\n");
  363.   printf("\nThis program must be distributed at or below the costs of the\n");
  364.   printf("media.  If you like this send a donation to support more Vware.\n");
  365.   printf("\nLoading the directory now (this can take time!)...\n");
  366.  
  367.   IntuitionBase = (struct IntuitionBase *)
  368.                   OpenLibrary("intuition.library", 0);
  369.   if (!IntuitionBase) goto no_intuition;
  370.   GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0);
  371.   if (!GfxBase) goto no_graphics;
  372.  
  373.   /************************
  374.     read in the directory
  375.   *************************/
  376.  
  377.   if (argc > 1)
  378.     strmfn(dir_name, NULL, argv[1], "#?", NULL);
  379.   else
  380.     strmfn(dir_name, NULL, NULL, "#?", NULL);
  381.  
  382.   count = getfnl(dir_name, names, sizeof(names), 0);
  383.   if (count > 0)
  384.   {
  385.     if (strbpl(pointers, 500, names) != count)
  386.     {
  387.       printf("Too many files in this directory.\n");
  388.       goto dir_error;
  389.     }
  390.     strsrt(pointers, count);
  391.  
  392.     /****************************************
  393.       The directory has now been read and sorted
  394.       it is time to walk through the files.
  395.       Currently this is displayed in the
  396.       console window, one file at a time.
  397.     ****************************************/
  398.  
  399.     w = (struct Window *) OpenWindow(&nw);
  400.     if (!w) goto no_window; /* can't open window error */
  401.     strmfn(start_name, NULL, argv[1], argv[2], NULL);
  402.     if (argc == 3) /* start at this file */
  403.     {
  404.       current_file = 0;
  405.       while (strcmpi(start_name, pointers[current_file]) &&
  406.              (current_file < count)) ++current_file;
  407.       --current_file;
  408.       next_file(1);
  409.       next_page(0);
  410.     }
  411.     else
  412.     {
  413.       next_file(0);      /* open a new file (the first) for display */
  414.       next_page(0);     /* display the next page in this file */
  415.     }
  416.     flag = TRUE;
  417.     while(flag)
  418.     {
  419.       Wait(1 << w->UserPort->mp_SigBit);
  420.       while(mess = (struct IntuiMessage *) GetMsg(w->UserPort))
  421.       {
  422.         func = ((struct Gadget *) mess->IAddress)->GadgetID;
  423.         class = mess->Class;
  424.         ReplyMsg(mess);
  425.         if (class == CLOSEWINDOW) flag = FALSE;
  426.         switch(func)
  427.         {
  428.           case PGUP:
  429.             if (feof(in))
  430.             {
  431.               next_file(1);
  432.               next_page(0);
  433.             }
  434.             else
  435.               next_page(1);
  436.             break;
  437.           case PGDN:
  438.             if (current_page == 0)
  439.             {
  440.               next_file(-1);
  441.               next_page(0);
  442.             }
  443.             else
  444.               next_page(-1);
  445.             break;
  446.           case NEXT:
  447.             next_file(1);
  448.             next_page(0);
  449.             break;
  450.           case PREV:
  451.             next_file(-1);
  452.             next_page(0);
  453.             break;
  454.         }
  455.       } /* end of while more messages */
  456.     }  /* end of while(flag) */
  457.     CloseWindow(w);
  458.   }
  459.   else
  460.   {
  461.     printf("Could not find any files.\n");
  462.     goto no_files;
  463.   }
  464. no_window:
  465. dir_error:
  466. no_files:
  467.   CloseLibrary(GfxBase);
  468. no_graphics:
  469.   CloseLibrary(IntuitionBase);
  470. no_intuition:
  471. }
  472.